extern crate core;

use core::ptr;

use std::time::Instant;

#[allow(dead_code)]
fn bug() {
	// let n : usize = usize::max_value();

	let a = b"0123456789abcdef";
	let n: usize = 1 << 63;
	// let a = b"012345";

	/**
	 * I construct a and n in this way. let's take a look at what is the overflowed a.len * n
	 * look like, surprisingly you got 0. your allocation will not fail but later memory corruption
	 * happens, this piece of bug can only reproduce in release mode. debug mode will automatically
	 * check overflow.
	 */

	println!("n = {}, a.len() = {}", n, a.len());
	let  overflowed_len: usize = a.len() * n;
	println!("overflowed len: {}", overflowed_len);


	let mut buf : Vec<u8> = Vec::with_capacity(a.len() * n);

	buf.extend(a);

	{
		let mut m = n >> 1;

		while m > 0 {
			unsafe {
				ptr::copy_nonoverlapping(buf.as_ptr(), (buf.as_mut_ptr() as *mut u8).add(buf.len()), buf.len());

				let buf_len = buf.len();
				buf.set_len(buf_len * 2);
			}

			m >>= 1;
		}
	}

	let rem_len = a.len() * n - buf.len();

	if rem_len > 0 {
		unsafe{
			ptr::copy_nonoverlapping(buf.as_ptr(), (buf.as_mut_ptr() as *mut u8).add(buf.len()), rem_len);

			let buf_cap = buf.capacity();
			buf.set_len(buf_cap);
		}
	}

	println!("{} {}", buf.len(), buf.capacity());
}

#[allow(dead_code)]
fn patch() {
	// let n : usize = usize::max_value();
	let n = 1 << 63;

	let a = b"0123456789abcdef";
	let mut buf: Vec<u8>  = Vec::with_capacity(a.len().checked_mul(n).expect("capacity overflow"));

	buf.extend(a);

	{
		let mut m = n >> 1;

		while m > 0 {
			unsafe {
				ptr::copy_nonoverlapping(buf.as_ptr(), (buf.as_mut_ptr() as *mut u8).add(buf.len()), buf.len());

				let buf_len = buf.len();
				buf.set_len(buf_len * 2);
			}

			m >>= 1;
		}
	}

	let rem_len = a.len() * n - buf.len();

	if rem_len > 0 {
		unsafe{
			ptr::copy_nonoverlapping(buf.as_ptr(), (buf.as_mut_ptr() as *mut u8).add(buf.len()), rem_len);

			let buf_cap = buf.capacity();
			buf.set_len(buf_cap);
		}
	}

	println!("{} {}", buf.len(), buf.capacity());
}

#[allow(dead_code)]
fn time1(n : usize) {
	let a = b"0123456789abcdef";
	let mut buf: Vec<u8>  = Vec::with_capacity(a.len().checked_mul(n).expect("capacity overflow"));
	buf.extend(a);

	let now = Instant::now();

	{
		let mut m = n >> 1;

		while m > 0 {
			unsafe {
				ptr::copy_nonoverlapping(buf.as_ptr(), (buf.as_mut_ptr() as *mut u8).add(buf.len()), buf.len());

				let buf_len = buf.len();
				buf.set_len(buf_len * 2);
			}

			m >>= 1;
		}
	}


	let elapsed = now.elapsed();

	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
    println!("Copy Seconds: {}", sec);
}

#[allow(dead_code)]
fn time2(n : usize) {
	let a = b"0123456789abcdef";
	let mut a_buf: Vec<u8> = Vec::with_capacity(a.len());
	let mut buf: Vec<u8>  = Vec::with_capacity(a.len().checked_mul(n).expect("capacity overflow"));
	a_buf.extend(a);

	let now = Instant::now();
	
	for _ in 0..n {
    	buf.append(& mut a_buf);
    }

    let elapsed = now.elapsed();

	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
    println!("Push Seconds: {}", sec);
}



fn main() {
	
	//time1(1<<10);
	//time2(1<<10);

	/*
	let mut buf: Vec<u8> = Vec::with_capacity(9);

	for _ in 0..10 {
		buf.push(12u8);
	}

	println!("{}", buf.capacity());

	println!("{}", buf[13]); */
	bug();
	// patch();
}
